Pythonのrequestsライブラリで、Response Bodyが無いときに「json()」した場合などの動作を確認してみた
JSON形式でないときに「response.json()」をすると、「requests.exceptions.JSONDecodeError」が発生します。
2024.09.13
Pythonでrequestsライブラリをよく使います。利用先のAPIによっては、Response Bodyがあったり無かったりします。そこで毎回、「あれ? どんな動作するんだっけ……?」となりがちだったので、改めて確認してみました。
おすすめの方
- Pythonのrequestsライブラリで、Response Bodyが無い場合の動作を知りたい方
- Pythonのrequestsライブラリで、Response BodyがJSON以外の場合の動作を知りたい方
最初に結論
- Response Bodyが無いとき、
response.json()
をすると、「requests.exceptions.JSONDecodeError」が発生する - Response BodyがあるけどJSON形式でないとき、
response.json()
をすると、「requests.exceptions.JSONDecodeError」が発生する
確認用のAPIをデプロイする
sam init
sam init \
--runtime python3.11 \
--name python-requests-test-api-sample \
--app-template hello-world \
--no-tracing \
--no-application-insights \
--structured-logging \
--package-type Zip
テンプレートファイル
2つのAPIを作成します。
- GET /not-response-body
- GET /not-json-response-body
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: python-requests-test-api-sample
Globals:
Function:
Timeout: 3
LoggingConfig:
LogFormat: JSON
Resources:
HelloWorld1Function:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world1/
Handler: app.lambda_handler
Runtime: python3.11
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api
Properties:
Path: /not-response-body
Method: get
HelloWorld1FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorld1Function}
HelloWorld2Function:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world2/
Handler: app.lambda_handler
Runtime: python3.11
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api
Properties:
Path: /not-json-response-body
Method: get
HelloWorld2FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorld2Function}
Lambdaコード
GET /not-response-body 用のLambda
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
}
GET /not-json-response-body 用のLambda
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": "not json message",
}
デプロイ
sam deploy \
--guided \
--region ap-northeast-1 \
--stack-name python-requests-test-api-sample-stack
実験用のPythonスクリプトを用意する
app.py
import requests
ENDPOINST = "https://xxx.execute-api.ap-northeast-1.amazonaws.com/Prod/"
PATH1 = "/not-response-body"
PATH2 = "/not-json-response-body"
def main():
print("### get_not_response_body()")
get_not_response_body()
print("\n")
print("### get_not_json_response_body()")
get_not_json_response_body()
def get_not_response_body():
response = requests.get(ENDPOINST + PATH1)
print(f"status code: {response.status_code}")
print(f"text type: {type(response.text)}")
print(f"text length: {len(response.text)}")
print(f"text: {response.text}")
try:
xxx = response.json()
except requests.exceptions.JSONDecodeError as e:
# この例外が発生する
print(f"json decode error: {e}")
def get_not_json_response_body():
response = requests.get(ENDPOINST + PATH2)
print(f"status code: {response.status_code}")
print(f"text type: {type(response.text)}")
print(f"text length: {len(response.text)}")
print(f"text: {response.text}")
try:
xxx = response.json()
except requests.exceptions.JSONDecodeError as e:
# この例外が発生する
print(f"json decode error: {e}")
if __name__ == "__main__":
main()
実行する
「requests.exceptions.JSONDecodeError」が発生しました。また、response.text
は空のstrになっていました(Noneではない)。
### get_not_response_body()
status code: 200
text type: <class 'str'>
text length: 0
text:
json decode error: Expecting value: line 1 column 1 (char 0)
### get_not_json_response_body()
status code: 200
text type: <class 'str'>
text length: 16
text: not json message
json decode error: Expecting value: line 1 column 1 (char 0)
さいごに
エラーハンドリングは大切なので、しっかり対応していきたいですね。どなたかの参考になれば幸いです。